package com.shawn.spring.boot.redis;

import com.shawn.spring.boot.redis.converter.BytesToMoneyConverter;
import com.shawn.spring.boot.redis.converter.MoneyToBytesConverter;
import com.shawn.spring.boot.redis.entity.CoffeeEntity;
import com.shawn.spring.boot.redis.service.CoffeeCacheService;
import com.shawn.spring.boot.redis.service.CoffeeService;
import java.time.Duration;
import java.util.Arrays;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.redis.JedisClientConfigurationBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.convert.RedisCustomConversions;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * @author shawn
 * @since 2020/9/3
 */
@Slf4j
@EnableTransactionManagement
@SpringBootApplication
@EnableJpaRepositories
@EnableRedisRepositories
public class RedisApplication implements ApplicationRunner {

  @Autowired private CoffeeService coffeeService;

  @Autowired private CoffeeCacheService cacheService;

  public static void main(String[] args) {
    SpringApplication.run(RedisApplication.class, args);
  }

  @Bean
  public RedisTemplate<String, CoffeeEntity> redisTemplate(
      RedisConnectionFactory redisConnectionFactory) {
    RedisTemplate<String, CoffeeEntity> template = new RedisTemplate<>();
    template.setConnectionFactory(redisConnectionFactory);
    return template;
  }

  @Bean
  public JedisClientConfigurationBuilderCustomizer customizer() {
    return builder -> builder.readTimeout(Duration.ofMinutes(2));
  }

  @Bean
  public RedisCustomConversions redisCustomConversions() {
    return new RedisCustomConversions(
        Arrays.asList(new MoneyToBytesConverter(), new BytesToMoneyConverter()));
  }

  @Override
  public void run(ApplicationArguments args) throws Exception {
    Optional<CoffeeEntity> c = coffeeService.findOneCoffee("mocha");
    log.info("Coffee {}", c);

    for (int i = 0; i < 5; i++) {
      c = coffeeService.findOneCoffee("mocha");
    }

    log.info("Value from Redis: {}", c);

    log.info("=====================redis repository===========================");

    Optional<CoffeeEntity> optional = cacheService.findSimpleCoffeeFromCache("latte");
    log.info("Coffee {}", optional);

    for (int i = 0; i < 5; i++) {
      optional = cacheService.findSimpleCoffeeFromCache("latte");
    }

    log.info("Value from Redis: {}", optional.get());
  }
}
